import json

from elasticsearch import Elasticsearch
from flask import Blueprint, current_app
from mozilla_schema_generator.glean_ping import GleanPing


bp = Blueprint("metrics", __name__, url_prefix="/api/metrics")


@bp.route("/search/<string:key>")
def search(key):
    es = Elasticsearch([{"host": current_app.config["ES_HOST"]}])
    query = {
        "query": {
            "bool": {
                "should": [
                    # Boost exact matches
                    {"term": {"name": {"value": key, "boost": 10}}},
                    {"prefix": {"name": key}},
                    {
                        "match": {
                            "description": {
                                "query": key,
                                "analyzer": "simple",
                                "fuzziness": "AUTO",
                            }
                        }
                    },
                ]
            }
        }
    }
    res = es.search(index="metrics", body=query)
    return res


# TODO:
# - Use the create index API to define settings and mappings explicitly.
#   https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-create-index.html


# The schema generator uses sets for some data structures. This will convert
# them to a list when we serialize to JSON when storing the probe
# representation to the database.
class SetEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, set):
            return list(obj)
        return json.JSONEncoder.default(self, obj)


@bp.cli.command("import")
def import_metrics():
    es = Elasticsearch([{"host": current_app.config["ES_HOST"]}])
    # TODO:
    # - We don't want to delete and insert each time. Come up with a way to
    #   uniquely identify each metric and insert or update these instead.
    es.indices.delete("metrics", ignore=[404])

    glean_products = [repo[0] for repo in GleanPing.get_repos()]
    for product in glean_products:
        print(product)
        metrics = GleanPing(product).get_probes()

        for metric in metrics:
            doc = metric.definition
            doc["product"] = product
            doc["name"] = metric.name
            es.index("metrics", json.dumps(doc, cls=SetEncoder))

        break
